//
// @Auther: by wujehy 
// @Email:wujehy@qq.com
// @Data:20-4-15
// @Time:上午11:01
//

#include "IoTDataBaseFactory.h"
#include <handy/logging.h>
#include <sstream>
#include "Business/internaltypes.h"

using namespace handy;

IoTDataBaseFactory::IoTDataBaseFactory(SQLite::Database *mDb)
{
    if (mDb == nullptr)
    {
        // 错误
        m_Db = nullptr;
    } else
    {
        // 成功 则储存
        m_Db = mDb;
    }

}


int IoTDataBaseFactory::initIoTTable()
{
    initSensorDataTable();
    initGatewayTable();
    initDeviceTable();
    initDeviceLoginTable();
    return 0;
}

int IoTDataBaseFactory::initSensorDataTable()
{
    info( "IoTDataBaseFactory::initSensorDataTable enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::initSensorDataTable  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    // 创建 表
    try
    {
        const bool bExists = m_Db->tableExists( "sensordata" );
        info( "SQLite table 'sensordata' exists=%d ", bExists );

        if (!bExists)
        {

            int ret = m_Db->exec( "CREATE TABLE `sensordata` ("
                                  " `id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,"
                                  " `uid` INTEGER NOT NULL, "
                                  " `GatewayId` INTEGER NOT NULL, "
                                  " `DevideId` INTEGER NOT NULL, "
                                  " `permission` INTEGER NOT NULL, "
                                  " `key` INTEGER NOT NULL, "
                                  " `data` TEXT NULL, "
                                  " `createat` INTEGER NOT NULL, "
                                  " `modifyat` INTEGER NOT NULL "
                                  ");" );

            m_Db->exec( "CREATE INDEX `sensordata_idx` ON `sensordata` (`uid` , `GatewayId` , `DevideId`)" );

            info( "IoTDataBaseFactory::initSensorDataTable() ret=%d", ret );
            return ERROR_SUCCESS;


        } else
        {
            // 存在 直接返回成功
            return ERROR_SUCCESS;
        }


    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::initSensorDataTable , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}


int IoTDataBaseFactory::initDeviceTable()
{
    info( "IoTDataBaseFactory::initDeviceTable enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::initDeviceTable  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    // 创建 表
    try
    {

        const bool bExists = m_Db->tableExists( "devices" );
        info( "SQLite table 'devices' exists=%d ", bExists );

        if (!bExists)
        {

            int ret = m_Db->exec( "CREATE TABLE `devices` ("
                                  " `did` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,"
                                  " `uid` INTEGER NOT NULL, "
                                  " `GatewayId` INTEGER NOT NULL, "
                                  " `DevideId` INTEGER NOT NULL, "
                                  " `permission` INTEGER NOT NULL, "
                                  " `Note` TEXT NULL, "
                                  " `Token` TEXT NULL, "
                                  " `createat` INTEGER NOT NULL, "
                                  " `modifyat` INTEGER NOT NULL "
                                  ");" );

            m_Db->exec( "CREATE INDEX `devices_idx` ON `devices` (`uid` , `GatewayId` , `DevideId`)" );
            info( "IoTDataBaseFactory::initIoTTable() ret=%d", ret );
            return ERROR_SUCCESS;


        } else
        {
            // 存在 直接返回成功
            return ERROR_SUCCESS;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::initDeviceTable , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int IoTDataBaseFactory::initDeviceLoginTable()
{
    info( "IoTDataBaseFactory::initDeviceLoginTable enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::initDeviceLoginTable  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    // 创建 表
    try
    {

        const bool bExists = m_Db->tableExists( "deviceLogin" );
        info( "SQLite table 'deviceLogin' exists=%d ", bExists );

        if (!bExists)
        {

            int ret = m_Db->exec( "CREATE TABLE `deviceLogin` ("
                                  " `logid` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,"
                                  " `GatewayId` INTEGER NOT NULL, "
                                  " `DevideId` INTEGER NOT NULL, "
                                  " `islogin` INTEGER NOT NULL, "
                                  " `enable` INTEGER NOT NULL, "
                                  " `modifyat` INTEGER NOT NULL, "
                                  " `createat` INTEGER NOT NULL"
                                  ");" );

            m_Db->exec( "CREATE INDEX `deviceLogin_idx` ON `deviceLogin` (`logid` , `GatewayId` , `DevideId` )" );
            info( "IoTDataBaseFactory::initDeviceLoginTable() ret=%d", ret );
            return ERROR_SUCCESS;

        } else
        {
            // 存在 直接返回成功
            return ERROR_SUCCESS;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::initDeviceLoginTable , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int IoTDataBaseFactory::initGatewayTable()
{
    info( "IoTDataBaseFactory::initGatewayTable enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::initGatewayTable  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    // 创建 表
    try
    {

        const bool bExists = m_Db->tableExists( "gateways" );
        info( "SQLite table 'gateways' exists=%d ", bExists );

        if (!bExists)
        {

            int ret = m_Db->exec( "CREATE TABLE `gateways` ("
                                  " `GatewayId` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT ,"
                                  " `uid` INTEGER NOT NULL, "
                                  " `Note` TEXT NULL, "
                                  " `createat` INTEGER NOT NULL, "
                                  " `modifyat` INTEGER NOT NULL "
                                  ");" );

            m_Db->exec( "CREATE INDEX `gateways_idx` ON `gateways` (`uid` , `GatewayId` )" );
            info( "IoTDataBaseFactory::initGatewayTable() ret=%d", ret );
            return ERROR_SUCCESS;


        } else
        {
            // 存在 直接返回成功
            return ERROR_SUCCESS;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::initGatewayTable , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

/********* 设备管理 start **********/
int IoTDataBaseFactory::addOrFindGatewayId(int64_t uid, std::vector<uint64_t> &outGids)
{
    info( "IoTDataBaseFactory::addOrFindGatewayId enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::addOrFindGatewayId m_Db == nullptr ... " );
        return ERROR_FAIL;
    }
    try
    {
        std::string sqlCheck = "select * from gateways where uid = ? ;";
        SQLite::Statement queryCheck( *m_Db, sqlCheck );

        queryCheck.bind( 1, uid );

        uint64_t currentGid = 0;
        while (queryCheck.executeStep())
        {
            currentGid = queryCheck.getColumn( 0 ).getInt64();
            outGids.push_back( currentGid );
        }

        info( "IoTDataBaseFactory::addOrFindGatewayId size = %d ", outGids.size());
        if (outGids.size() > 0)
        {
            return ERROR_SUCCESS;
        }

        // 不存在 则 创建
        queryCheck.reset();

        std::string insertSql = "insert into gateways ( uid, createat, modifyat) values ( ? , ? , ?);";
        int64_t currTime = util::timeMilli();

        SQLite::Statement queryInsert( *m_Db, insertSql );
        queryInsert.bind( 1, uid );
        queryInsert.bind( 2, currTime );
        queryInsert.bind( 3, currTime );

        int nb = queryInsert.exec();
        info( "IoTDataBaseFactory::addOrFindGatewayId nb = %d ", nb );

        queryCheck.bind( 1, uid );
        while (queryCheck.executeStep())
        {
            currentGid = queryCheck.getColumn( 0 ).getInt64();
            outGids.push_back( currentGid );
        }

        info( "IoTDataBaseFactory::addOrFindGatewayId 2 size = %d ", outGids.size());
        return ERROR_SUCCESS;


    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::addOrFindGatewayId , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }

}

int IoTDataBaseFactory::addDevice( int64_t uid, uint64_t GatewayId, int32_t permission, std::string &note, uint64_t &outDeviceid)
{

    info( "IoTDataBaseFactory::addDevice enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::addDevice  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }
    try
    {
        // TODO
        int64_t currTime = util::timeMilli();

        std::string findGid = "select * from gateways where uid = ? and GatewayId = ?;";

        //判断网关 是不是我的
        SQLite::Statement queryFindGid( *m_Db, findGid );
        queryFindGid.bind( 1, uid );
        queryFindGid.bind( 2, (int64_t) GatewayId );

        int gidSize = 0;
        if (queryFindGid.executeStep())
        {
            gidSize = queryFindGid.getColumnCount();
        }

        info( "IoTDataBaseFactory::addDevice gidSize =%d  ", gidSize );


        if (gidSize == 0)
        {
            // 不是我的 网关
            info( "IoTDataBaseFactory::addDevice , This is not mine" );
            return ERROR_FAIL;
        }



        uint64_t lastDeviceid = 0;
        std::string findLastSql = "select DevideId from devices where GatewayId = ? ORDER BY DevideId DESC ;";
        SQLite::Statement queryFind( *m_Db, findLastSql );
        queryFind.bind( 1, (int64_t) GatewayId );

        if (queryFind.executeStep())
        {
            lastDeviceid = queryFind.getColumn( 0 ).getInt64();
        } else
        {
//            return ERROR_FAIL;
        }
        queryFind.reset();
        std::string insertSql = "insert into devices (uid, GatewayId, DevideId,permission ,Note, createat, modifyat) values ( ? , ? , ? , ? , ? , ? , ?);";

        SQLite::Statement queryInsert( *m_Db, insertSql );

        outDeviceid = lastDeviceid + 1;
        queryInsert.bind( 1, uid );
        queryInsert.bind( 2, (int64_t) GatewayId );
        queryInsert.bind( 3, (int64_t) outDeviceid );
        queryInsert.bind( 4, permission );
        queryInsert.bind( 5, note );
        queryInsert.bind( 6, currTime );
        queryInsert.bind( 7, currTime );

        int nb = queryInsert.exec();

        info( "IoTDataBaseFactory::addDevice  nb = %d ", nb );

        return ERROR_SUCCESS;

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::addDevice , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }

    return 0;
}

int IoTDataBaseFactory::updataDeviceToken(int64_t uid, uint64_t GatewayId, uint64_t DeviceId, std::string &newToken)
{
    info( "IoTDataBaseFactory::updataDeviceToken enter ... " );

    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::updataDeviceToken  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        std::string sql = "update devices set Token = ? where uid = ? and GatewayId = ? and DevideId = ? ;";

        SQLite::Statement query( *m_Db, sql );
        query.bind( 1, newToken );
        query.bind( 2, uid );
        query.bind( 3, (int64_t) GatewayId );
        query.bind( 4, (int64_t) DeviceId );

        int nb = query.exec();

        debug( "IoTDataBaseFactory::updataDeviceToken : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::updataDeviceToken , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int IoTDataBaseFactory::findDevices(
        std::vector<DeviceDataType> &devices, int64_t uid, uint64_t GatewayId,
        int32_t permission)
{
    info( "IoTDataBaseFactory::findDevices enter ... " );

    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::findDevices  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    bool haveUid = false;

    if (uid > 0)
    {
        haveUid = true;
    }

    try
    {
        // TODO
        std::string sql;
        if (haveUid)
        {
            sql = "select * from devices where uid = ? and GatewayId = ? and permission >= ?;";
        } else
        {
            sql = "select * from devices where GatewayId = ? and permission >= ?;";
        }

        SQLite::Statement query( *m_Db, sql );
        if (haveUid)
        {
            query.bind( 1, uid );
            query.bind( 2, (int64_t) GatewayId );
            query.bind( 3, permission );
        } else
        {
            query.bind( 1, (int64_t) GatewayId );
            query.bind( 2, 4 );
        }

        DeviceDataType currDevice;
        while (query.executeStep())
        {

            currDevice.uid = query.getColumn( "uid" ).getInt64();
            currDevice.GatewayId = query.getColumn( "GatewayId" ).getInt64();
            currDevice.DevideId = query.getColumn( "DevideId" ).getInt64();
            currDevice.permission = query.getColumn( "permission" ).getInt64();
            currDevice.Token = query.getColumn( "Token" ).getInt64();
            currDevice.Note = query.getColumn( "Note" ).getInt64();
            currDevice.create = query.getColumn( "createat" ).getInt64();

            devices.push_back( currDevice );
        }

        debug( "IoTDataBaseFactory::insertData  : size =%d", devices.size());

        return ERROR_SUCCESS;


    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::findDevices , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}
/********* 设备管理 end **********/



/********* 数据管理 start **********/
int IoTDataBaseFactory::insertData(SensorDataType &data)
{

    info( "IoTDataBaseFactory::insertData enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::insertData  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "insert into sensordata (uid, GatewayId, DevideId, permission, key, data, createat, modifyat) values ( ? , ? , ? , ? , ? , ? , ? , ? );";

        SQLite::Statement query( *m_Db, sql );

        int64_t currTime = util::timeMilli();
        query.bind( 1, data.uid );
        query.bind( 2, (int64_t) data.GatewayId );
        query.bind( 3, (int64_t) data.DeviceId );
        query.bind( 4, data.permission );
        query.bind( 5, data.key );
        query.bind( 6, data.data );
        query.bind( 7, currTime );
        query.bind( 8, currTime );


        int nb = query.exec();
        debug( "IoTDataBaseFactory::insertData  : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }


    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::insertData , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }

}

int IoTDataBaseFactory::findDataByUid(
        std::vector<SensorDataType> &outdatas, int64_t uid, uint64_t GatewayId,
        uint64_t DevideId, int32_t permission, int32_t key, int limit, int direction,
        int64_t targetTime)
{
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::findDataByUid  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    // sql

    bool haveUid = false;
    bool haveGatewayId = false;
    bool haveDevideId = false;
    bool havePermission = false;
    bool haveKey = false;

    bool haveDirection = false;
    bool haveTargetTime = false;


    if (uid > 0)
    {
        haveUid = true;
    } else
    {
        info( "not find uid" );
    }

    if (GatewayId > 0)
    {
        haveGatewayId = true;
    }

    if (DevideId > 0)
    {
        haveDevideId = true;
    }

    if (permission > 0)
    {
        havePermission = true;
    }

    if (direction > 0)
    {
        haveDirection = true;
    }

    if (targetTime > 0)
    {
        haveTargetTime = true;
    }

    if (key > 0)
    {
        haveKey = true;
        haveDirection = false;
        haveTargetTime = false;
    }

    // 拼接
    std::stringstream ssql;
    ssql << "select * from `sensordata` ";

    if (haveUid)
    {
        ssql << " where `uid` = ? ";
    } else
    {
        ssql << " where 1 = 1 ";
    }

    // 存在 其他值 直接 拼接
    if (haveGatewayId || haveDevideId || havePermission || haveKey)
    {
        if (haveGatewayId)
        {
            ssql << " and `GatewayId` = ? ";
        }

        if (haveDevideId)
        {
            ssql << " and `DevideId` = ? ";
        }

        if (havePermission)
        {
            ssql << " and `permission` >= ? ";
        }

        if (haveKey)
        {
            ssql << " and `key` = ? ";
        }

        if (haveDirection && haveTargetTime)
        {
            if (direction == 1)
            {
                // 旧消息
                ssql << " and `createat` < ? ORDER By createat LIMIT ? ";
            } else if (direction == 2)
            {
                ssql << " and `createat` > ? ORDER By time DESC LIMIT ? ";
            }
        }
    }

    ssql << " ; ";

    info( "sql : %s ", ssql.str().c_str());
    try
    {
        // TODO
        SQLite::Statement query( *m_Db, ssql.str());
        int oti = 1;
        if (haveUid)
        {
            query.bind( oti, uid );
            oti++;
        }


        if (haveGatewayId)
        {
            query.bind( oti, (int64_t) GatewayId );
            oti++;
        }
        if (haveDevideId)
        {
            query.bind( oti, (int64_t) DevideId );
            oti++;
        }

        if (havePermission)
        {
            query.bind( oti, permission );
            oti++;
        }

        if (haveKey)
        {
            query.bind( oti, key );
            oti++;
        }
        if (haveDirection && haveTargetTime)
        {
            query.bind( oti, targetTime );
            oti++;

            query.bind( oti, limit );
            oti++;
        }


        while (query.executeStep())
        {
            SensorDataType temp;
            temp.uid = query.getColumn( 1 ).getInt64();
            temp.GatewayId = query.getColumn( 2 ).getInt64();
            temp.DeviceId = query.getColumn( 3 ).getInt64();
            temp.permission = query.getColumn( 4 ).getInt();
            temp.key = query.getColumn( 5).getInt();
            temp.data = query.getColumn( 6 ).getString();
            temp.create = query.getColumn( 7 ).getInt64();
            temp.modifyat = query.getColumn( 8 ).getInt64();
            outdatas.push_back( temp );
        }
        info( "IoTDataBaseFactory::findDataByUid  getData success %d ", outdatas.size());

        return ERROR_SUCCESS;

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::findDataByUid , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int IoTDataBaseFactory::findDataByPublic(
        std::vector<SensorDataType> &outdatas, uint64_t GatewayId, uint64_t DevideId,
        int limit, int direction, int64_t targetTime)
{
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::findDataByPublic  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    if (!(direction == 1 || direction == 2))
    {
        info( "IoTDataBaseFactory::findDataByPublic  direction = %d ", direction );
        return ERROR_FAIL;
    }
    try
    {
        std::string sql;
        if (direction == 1)
        {
            sql = "select * from sensordata where GatewayId = ? and DevideId = ? and permission = ? and createat < ? ORDER By createat LIMIT ? ; ";

        } else if (direction == 2)
        {
            sql = "select * from sensordata where GatewayId = ? and DevideId = ? and permission = ? and createat > ?  ORDER By createat DESC LIMIT ?; ";

        }
        SQLite::Statement query( *m_Db, sql );

        query.bind( 1, (int64_t) GatewayId );
        query.bind( 2, (int64_t) DevideId );
        query.bind( 3, 4 );
        query.bind( 4, targetTime );
        query.bind( 5, limit );

        while (query.executeStep())
        {
            SensorDataType temp;
            temp.uid = query.getColumn( 1 ).getInt64();
            temp.GatewayId = query.getColumn( 2 ).getInt64();
            temp.DeviceId = query.getColumn( 3 ).getInt64();
            temp.permission = query.getColumn( 4 ).getInt();
            temp.key = query.getColumn( 5 ).getInt();
            temp.data = query.getColumn( 6 ).getString();
            temp.create = query.getColumn( 7 ).getInt64();
            temp.modifyat = query.getColumn( 8 ).getInt64();

            outdatas.push_back( temp );
        }

        info( "IoTDataBaseFactory::findDataByPublic  getData success %d ", outdatas.size());
        return ERROR_SUCCESS;
    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::findDataByPublic , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
}

int IoTDataBaseFactory::checkMyDevice(int64_t uid, uint64_t GatewayId, uint64_t DevideId)
{
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::checkMyDevice  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "select * from sensordata where uid = ? and GatewayId = ? and DevideId = ? ;";
        SQLite::Statement query( *m_Db, sql );

        query.bind( 1, uid );
        query.bind( 2, (int64_t) GatewayId );
        query.bind( 3, (int64_t) DevideId );

        int size = 0;

        if (query.executeStep())
        {
            size = query.getColumnCount();
        }

        info( "IoTDataBaseFactory::checkMyDevice  uid size = %d ", size );

        if (size > 0)
        {
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::checkMyDevice , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }

}

/********* 数据管理 end **********/


/******* 设备 登录管理 start ********/
int IoTDataBaseFactory::loginDeviceByToken(std::string &token)
{

    info( "IoTDataBaseFactory::loginDeviceByToken enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::loginDeviceByToken  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        std::string sqlFindDevice = "select * from devices where Token = ? ;";

        SQLite::Statement queryFindDevice( *m_Db, sqlFindDevice );
        queryFindDevice.bind( 1, token );
        uint64_t currentGatewayId = 0, currentDevideId = 0;
        if (queryFindDevice.executeStep())
        {
            currentGatewayId = queryFindDevice.getColumn( "GatewayId" ).getInt64();
            currentDevideId = queryFindDevice.getColumn( "DevideId" ).getInt64();
        }
        queryFindDevice.reset();
        if (!(currentDevideId != 0 && currentGatewayId != 0))
        {
            warn( " IoTDataBaseFactory::loginDeviceByToken no found device " );
            return ERROR_FAIL;
        }

        //  设备存在 才能下一步
        int64_t lastid = 0;
        if (checkLoginDevice( currentGatewayId, currentDevideId, lastid ))
        {
            // 在线
            //增加心跳

            int ret = HeartBeatDevice( currentGatewayId, currentDevideId, lastid );

            if (ret == ERROR_SUCCESS)
            {
                info( "IoTDataBaseFactory::loginDeviceByToken call HeartBeatDevice = %d ", ret );
            }
            return ERROR_SUCCESS;
        } else
        {
            // 不在线 登录
            //新增
        }
        std::string sqlInsert = "insert into deviceLogin (GatewayId, DevideId, islogin, enable ,modifyat, createat) values (? , ? , ? , ? , ? , ? );";
        SQLite::Statement queryInsert( *m_Db, sqlInsert );
        int64_t currentTime = util::timeMilli();
        queryInsert.bind( 1, (int64_t) currentGatewayId );
        queryInsert.bind( 2, (int64_t) currentDevideId );
        queryInsert.bind( 3, 1 );
        queryInsert.bind( 4, 1 );
        queryInsert.bind( 5, currentTime );
        queryInsert.bind( 6, currentTime );

        int nb = queryInsert.exec();
        debug( "IoTDataBaseFactory::loginDeviceByToken  : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::loginDeviceByToken , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

bool IoTDataBaseFactory::checkLoginDevice(uint64_t GatewayId, uint64_t DevideId, int64_t &lastLogid)
{
    info( "IoTDataBaseFactory::checkLoginDevice enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::checkLoginDevice  m_Db == nullptr ... " );
        return false;
    }

    try
    {
        // TODO
        std::string sql = "select * from deviceLogin where GatewayId = ? and DevideId = ? and islogin = ? and enable = ? ORDER BY modifyat DESC ;";
        SQLite::Statement query( *m_Db, sql );
        query.bind( 1, (int64_t) GatewayId );
        query.bind( 2, (int64_t) DevideId );
        query.bind( 3, 1 );
        query.bind( 4, 1 );
        int nb = 0;
        int64_t lastTime = 0;
        int64_t currentTime = util::timeMilli();
        int64_t currLastId = 0;
        if (query.executeStep())
        {
            nb = query.getColumnCount();
            lastTime = query.getColumn( "modifyat" );
            currLastId = query.getColumn( 0 ).getInt64();
        }

        info( "IoTDataBaseFactory::checkLoginDevice lastTime = %d , current = %d , nb = %d , lastid = %d ", lastTime,
              currentTime, nb, currLastId );
        lastLogid = currLastId;
        if ((currentTime - lastTime) < (15 * 60 * 1000) && nb > 0)
        {
            return true;
        } else
        {
            // 超时 , 被动退出
            logoutDevice( GatewayId, DevideId, currLastId );
            return false;
        }


    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::checkLoginDevice , SQLite exception: %d", e.what());
        return false;
    }
}

int IoTDataBaseFactory::logoutDevice(uint64_t GatewayId, uint64_t DevideId, int64_t lastLogid)
{
    info( "IoTDataBaseFactory::logoutDevice enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::logoutDevice  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "update deviceLogin set modifyat = ?  , islogin = ? , enable = ?  where logid = ? and GatewayId = ? and DevideId = ?; ";
        SQLite::Statement query( *m_Db, sql );

        int64_t currentTime = util::timeMilli();

        query.bind( 1, currentTime );
        query.bind( 2, 0 );
        query.bind( 3, 0 );
        query.bind( 4, lastLogid );
        query.bind( 5, (int64_t) GatewayId );
        query.bind( 6, (int64_t) DevideId );
        int nb = query.exec();
        debug( "IoTDataBaseFactory::logoutDevice  : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }


    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::logoutDevice , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

int IoTDataBaseFactory::HeartBeatDevice(uint64_t GatewayId, uint64_t DevideId, int64_t lastLogid)
{
    info( "IoTDataBaseFactory::HeartBeatDevice enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::HeartBeatDevice  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // 查询最新的登录时间
        std::string sql = "update deviceLogin set modifyat = ? where logid = ? and GatewayId = ? and DevideId = ?;";
        SQLite::Statement query( *m_Db, sql );

        int64_t currentTime = util::timeMilli();
        query.bind( 1, currentTime );
        query.bind( 2, lastLogid );
        query.bind( 3, (int64_t) GatewayId );
        query.bind( 4, (int64_t) DevideId );

        int nb = query.exec();
        debug( "IoTDataBaseFactory::HeartBeatDevice  : nb =%d", nb );
        if (nb > 0)
        {
            // 影响 1 条以上 才成功,否则是失败
            return ERROR_SUCCESS;
        } else
        {
            return ERROR_FAIL;
        }

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::HeartBeatDevice , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}


int IoTDataBaseFactory::findDeviceByToken(DeviceDataType &deviceDataType, std::string token)
{
    info( "IoTDataBaseFactory::findDeviceBuToken enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::findDeviceBuToken  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "select * from devices where Token = ? ;";
        SQLite::Statement query( *m_Db, sql );

        query.bind( 1, token );
        if (query.executeStep())
        {
            deviceDataType.uid = query.getColumn( "uid" ).getInt64();
            deviceDataType.GatewayId = query.getColumn( "GatewayId" ).getInt64();
            deviceDataType.DevideId = query.getColumn( "DevideId" ).getInt64();
            deviceDataType.permission = query.getColumn( "permission" ).getInt64();
            deviceDataType.Token = query.getColumn( "Token" ).getInt64();
            deviceDataType.Note = query.getColumn( "Note" ).getInt64();
            deviceDataType.create = query.getColumn( "createat" ).getInt64();
            info( "IoTDataBaseFactory::findDeviceBuToken success !" );
            return ERROR_SUCCESS;
        }

        info( "IoTDataBaseFactory::findDeviceBuToken fail !" );

        return ERROR_FAIL;

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::findDeviceBuToken , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

int IoTDataBaseFactory::findDeviceToken(
        DeviceDataType &deviceDataType, int64_t uid, uint64_t GatewayId,
        uint64_t DeviceId)
{
    info( "IoTDataBaseFactory::findDeviceToken enter ... " );
    if (m_Db == nullptr)
    {
        info( "IoTDataBaseFactory::findDeviceToken  m_Db == nullptr ... " );
        return ERROR_FAIL;
    }

    try
    {
        // TODO
        std::string sql = "select * from devices where uid = ?  and GatewayId = ? and DevideId = ? ;";
        SQLite::Statement query( *m_Db, sql );

        query.bind( 1, uid );
        query.bind( 2, (int64_t) GatewayId );
        query.bind( 3, (int64_t) DeviceId );
        if (query.executeStep())
        {
            deviceDataType.uid = query.getColumn( "uid" ).getInt64();
            deviceDataType.GatewayId = query.getColumn( "GatewayId" ).getInt64();
            deviceDataType.DevideId = query.getColumn( "DevideId" ).getInt64();
            deviceDataType.permission = query.getColumn( "permission" ).getInt64();
            deviceDataType.Token = query.getColumn( "Token" ).getInt64();
            deviceDataType.Note = query.getColumn( "Note" ).getInt64();
            deviceDataType.create = query.getColumn( "createat" ).getInt64();
            info( "IoTDataBaseFactory::findDeviceToken success !" );
            return ERROR_SUCCESS;
        }

        info( "IoTDataBaseFactory::findDeviceToken fail !" );

        return ERROR_FAIL;

    } catch (std::exception &e)
    {
        debug( " IoTDataBaseFactory::findDeviceToken , SQLite exception: %d", e.what());
        return ERROR_FAIL;
    }
    return 0;
}

/******* 设备 登录管理 end ********/

//info("IoTDataBaseFactory::insertData enter ... ");
//if (m_Db == nullptr)
//{
//info("IoTDataBaseFactory::insertData  m_Db == nullptr ... ");
//return ERROR_FAIL;
//}
//
//try
//{
//// TODO
//
//
//
//} catch (std::exception &e)
//{
//debug(" IoTDataBaseFactory::insertData , SQLite exception: %d", e.what());
//return ERROR_FAIL;
//}
//return 0;